﻿//#include<iostream>
//#include<assert.h>
//#include"CustomVector.hPP"
//#include"matrix.hpp"
//#include "mathlibiary.h"
//using namespace std;
//using namespace MyCustomVector;
//无所谓了
//指针
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>

#include <Windows.h>
#include <tchar.h>

#include <cassert>
#include <cstdio>

#include "maths.h"
#include "win32.h"

//typedef unsigned int IUINT32;
////& 运算符 寻址
////* 运算符 取值
////数学库
//typedef struct
//{
//	float m[4][4];
//} matrix_t;
//typedef struct 
//{
//	float x, y, z, w;
//} vector_t;
//typedef vector_t point_t;
//
//int CMD(int x,int min,int max){ (x < min) ? min : ((x > max) ? max : x); }
//
//// 计算插值：t 为 [0, 1] 之间的数值
//float interp(float x1, float x2, float t) { return x1 + (x2 - x1) * t; }
//
//// | v |
//float vector_length(const vector_t* v) {
//	float sq = v->x * v->x + v->y * v->y + v->z * v->z;
//	return (float)sqrt(sq);
//}
//
//// z = x + y
//void vector_add(vector_t* z, const vector_t* x, const vector_t* y) {
//	z->x = x->x + y->x;
//	z->y = x->y + y->y;
//	z->z = x->z + y->z;
//	z->w = 1.0;
//}
//
//// z = x - y
//void vector_sub(vector_t* z, const vector_t* x, const vector_t* y) {
//	z->x = x->x - y->x;
//	z->y = x->y - y->y;
//	z->z = x->z - y->z;
//	z->w = 1.0;
//}
//
//// 矢量点乘
//float vector_dotproduct(const vector_t* x, const vector_t* y) {
//	return x->x * y->x + x->y * y->y + x->z * y->z;
//}
//
//// 矢量叉乘
//void vector_crossproduct(vector_t* z, const vector_t* x, const vector_t* y) {
//	float m1, m2, m3;
//	m1 = x->y * y->z - x->z * y->y;
//	m2 = x->z * y->x - x->x * y->z;
//	m3 = x->x * y->y - x->y * y->x;
//	z->x = m1;
//	z->y = m2;
//	z->z = m3;
//	z->w = 1.0f;
//}
//
//// 矢量插值，t取值 [0, 1]
//void vector_interp(vector_t* z, const vector_t* x1, const vector_t* x2, float t) {
//	z->x = interp(x1->x, x2->x, t);
//	z->y = interp(x1->y, x2->y, t);
//	z->z = interp(x1->z, x2->z, t);
//	z->w = 1.0f;
//}
//
//// 矢量归一化
//void vector_normalize(vector_t* v) {
//	float length = vector_length(v);
//	if (length != 0.0f) {
//		float inv = 1.0f / length;
//		v->x *= inv;
//		v->y *= inv;
//		v->z *= inv;
//	}
//}
window_t* window = NULL;

static LRESULT CALLBACK msg_callback(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
	switch (msg)
	{
	case WM_CLOSE:
		window->is_close = 1;
		break;
	case WM_KEYDOWN:
		window->keys[wparam & 511] = 1;
		break;
	case WM_KEYUP:
		window->keys[wparam & 511] = 0;
		break;
	case WM_LBUTTONDOWN:
		window->mouse_info.orbit_pos = get_mouse_pose();
		window->buttons[0] = 1;
	case WM_LBUTTONUP:
		window->buttons[0] = 0;
		break;
	case WM_RBUTTONDOWN:
		window->mouse_info.orbit_pos = get_mouse_pose();
		window->buttons[1] = 1;
		break;
	case WM_RBUTTONUP:
		window->buttons[1] = 0;
		break;
	case WM_MOUSEHWHEEL:
		window->mouse_info.wheel_delta = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA;
		break;
	default:return DefWindowProc(hwnd, msg, wparam, lparam);
	}
	return 0;
}

/*
	UINT        style;
	WNDPROC     lpfnWndProc;
	int         cbClsExtra;
	int         cbWndExtra;
	HINSTANCE   hInstance;
	HICON       hIcon;
	HCURSOR     hCursor;
	HBRUSH      hbrBackground;
	LPCSTR      lpszMenuName;
	LPCSTR      lpszClassName;
*/


static void register_window_class()
{
	ATOM atom;
	//初始化结构体
	WNDCLASS wndclass;
	wndclass.style = CS_BYTEALIGNCLIENT;//窗口风格
	wndclass.lpfnWndProc = (WNDPROC)msg_callback;//回调函数
	wndclass.cbClsExtra = 0;//紧跟在窗口类尾部的一块额外空间，不用则设为0
	wndclass.cbWndExtra = 0;//紧跟在窗口实例尾部的一块额外空间，不用则设为0
	wndclass.hInstance = GetModuleHandle(NULL);//当前实例句柄
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);//任务栏图标
	wndclass.hCursor = LoadCursor(NULL, IDC_CROSS);//光标样式
	wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);//背景
	wndclass.lpszMenuName = NULL;//菜单
	wndclass.lpszClassName = NULL;//该窗口类的名字

	atom = RegisterClass(&wndclass);//注册窗口类
	assert(atom != 0);
}
/*
		DWORD      biSize;
		LONG       biWidth;
		LONG       biHeight;
		WORD       biPlanes;
		WORD       biBitCount;
		DWORD      biCompression;
		DWORD      biSizeImage;
		LONG       biXPelsPerMeter;
		LONG       biYPelsPerMeter;
		DWORD      biClrUsed;
		DWORD      biClrImportant;
*/
static void init_bm_header(BITMAPINFOHEADER &bi,int width,int height)
{
	memset(&bi, 0, sizeof(BITMAPINFOHEADER));
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = width;
	bi.biHeight = -height;//从上到下
	bi.biPlanes = 1;
	bi.biBitCount = 32;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = width * height * 4;
}
int window_init(int width,int height,const char* title)
{
	window = (window_t*)malloc(sizeof(window_t));
	memset(window, 0, sizeof(window_t));
	window->is_close = 0;

	RECT rect = { 0,0,width,height };//一个矩形范围 左上右下
	int wx, wy, sx, sy;
	LPVOID ptr;
	HDC hdc;//设备环境，h代表句柄，handle
	BITMAPINFOHEADER bi;

	//注册窗口类
	register_window_class();

	//创建窗口
	window->h_window = CreateWindowW(NULL, NULL, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
		0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
	//初始化位图头格式
	init_bm_header(bi, width, height);
	//
	hdc = GetDC(window->h_window);
	window->mem_dc = CreateCompatibleDC(hdc);
	ReleaseDC(window->h_window, hdc);
	//
	window->bm_dib = CreateDIBSection(window->mem_dc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, &ptr, 0, 0);
	assert(window->bm_dib != NULL);

	window->bm_old = (HBITMAP)SelectObject(window->mem_dc, window->bm_dib);
	window->window_fb = (unsigned char*)ptr;

	window->height = height;
	window->width = width;

	AdjustWindowRect(&rect, GetWindowLong(window->h_window, GWL_STYLE),0);
	wx = rect.right - rect.left;
	wy = rect.bottom - rect.top;
	sx = (GetSystemMetrics(SM_CXSCREEN) - wx);
	sy = (GetSystemMetrics(SM_CXSCREEN) - wy);

	if (sy<0)
	{
		sy = 0;
	}
	SetWindowPos(window->h_window, NULL, sx, sy, wx, wy, (SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW));
	SetForegroundWindow(window->h_window);
	ShowWindow(window->h_window, SW_NORMAL);
	//
	msg_dispatch();

	//
	memset(window->window_fb, 0, width * height * 4);
	memset(window->keys,0,sizeof(char)*512);
	return 0;
}

int window_destory()
{
	if (window->mem_dc)
	{
		if (window->bm_old)
		{
			SelectObject(window->mem_dc, window->bm_old);
			window->bm_old = NULL;
		}
		DeleteDC(window->mem_dc);
		window->mem_dc = NULL;
	}
	if (window->bm_dib)
	{
		DeleteObject(window->bm_dib);
		window->bm_dib = NULL;
	}
	if (window->h_window)
	{
		CloseWindow(window->h_window);
		window->h_window = NULL;
	}
	free(window);
	return 0;
}

void msg_dispath()
{
	MSG msg;
	while (1)
	{
		// Peek不阻塞，Get会阻塞，PM_NOREMOVE表示如果有消息不处理（留给接下来的Get处理）
		if (!PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))break;
		if (!GetMessage(&msg,NULL,0,0))break;

		TranslateMessage(&msg);//转换消息 虚拟按键->字符
		DispatchMessage(&msg); //传送消息给回调
	}
}
static void window_display()
{
	LOGFONT logfont;
	ZeroMemory(&logfont, sizeof(LOGFONT));
	logfont.lfCharSet = ANSI_CHARSET;
	logfont.lfHeight = 20;//设置字体的大小
	HFONT hfont = CreateFontIndirect(&logfont);

	HDC hdc = GetDC(window->h_window);
	//目标举行的左上角(x,y), 宽度，高度，上下文指针
	SelectObject(window->mem_dc, hfont);
	SetTextColor(window->mem_dc, RGB(190, 190, 190));
	SetBkColor(window->mem_dc, RGB(80, 80, 80));
	//把兼容性DC的数据传到真正的DC上
	BitBlt(hdc, 0, 0, window->width, window->height, window->mem_dc, 0, 0, SRCCOPY);
	ReleaseDC(window->h_window, hdc);
}

void window_draw(unsigned char* framebuffer)
{
	int i, j;
	for (int i = 0; i < window->height; i++)
	{
		for (int j = 0; j < window->width; j++)
		{
			int index = (i * window->width + j) * 4;
			window->window_fb[index] = framebuffer[index + 2];
			window->window_fb[index + 1] = framebuffer[index + 1];
			window->window_fb[index + 2] = framebuffer[index];
		}
	}
	window_display();
}

Vector2 get_mouse_pose()
{
	POINT point;
	GetCursorPos(&point);
	ScreenToClient(window->h_window, &point);
	return Vector2((float)point.x, (float)point.y);
}
static double get_native_time(void)
{
	static double period = -1;
	LARGE_INTEGER counter;
	if (period < 0) {
		LARGE_INTEGER frequency;
		QueryPerformanceFrequency(&frequency);
		period = 1 / (double)frequency.QuadPart;
	}
	QueryPerformanceCounter(&counter);
	return counter.QuadPart * period;
}

float platform_get_time(void)
{
	static double initial = -1;
	if (initial < 0) {
		initial = get_native_time();
	}
	return (float)(get_native_time() - initial);
}